#! /bin/sh -eu

# Copy files from /usr/share/maven/ref into ${MAVEN_CONFIG}
# So the initial ~/.m2 is set with expected content.
# Don't override, as this is just a reference setup

copy_reference_files() {
  local log="$MAVEN_CONFIG/copy_reference_file.log"
  local ref="/usr/share/maven/ref"
  echo "copy_reference_files ..."
  if mkdir -p "${MAVEN_CONFIG}/repository" && touch "${log}" > /dev/null 2>&1 ; then
      cd "${ref}"
      local reflink=""
      if cp --help 2>&1 | grep -q reflink ; then
          reflink="--reflink=auto"
      fi
      if [ -n "$(find "${MAVEN_CONFIG}/repository" -maxdepth 0 -type d -empty 2>/dev/null)" ] ; then
          # destination is empty...
          echo "--- Copying all files to ${MAVEN_CONFIG} at $(date)" >> "${log}"
          cp -rv ${reflink} . "${MAVEN_CONFIG}" >> "${log}"
      else
          # destination is non-empty, copy file-by-file
          echo "--- Copying individual files to ${MAVEN_CONFIG} at $(date)" >> "${log}"
          find . -type f -exec sh -eu -c '
              log="${1}"
              shift
              reflink="${1}"
              shift
              for f in "$@" ; do
                  if [ ! -e "${MAVEN_CONFIG}/${f}" ] || [ -e "${f}.override" ] ; then
                      mkdir -p "${MAVEN_CONFIG}/$(dirname "${f}")"
                      cp -rv ${reflink} "${f}" "${MAVEN_CONFIG}/${f}" >> "${log}"
                  fi
              done
          ' _ "${log}" "${reflink}" {} +
      fi
      echo >> "${log}"
  else
    echo "Can not write to ${log}. Wrong volume permissions? Carrying on ..."
  fi
}

owd="$(pwd)"
copy_reference_files
unset MAVEN_CONFIG

cd "${owd}"
unset owd

pull() {
  echo "==> Start git pull latest commits by 'git clone -b ${BRANCH} git@${STASH_GIT_HOST}:${ORG}/${GIT_REPO}.git  ${APP_PATH}'..."
   export GIT_SSH_COMMAND='ssh -o StrictHostKeyChecking=no'  # acknowledge public key automatically
  rm -rf "${APP_PATH}"
  git clone -b "${BRANCH}" git@"${STASH_GIT_HOST}":"${ORG}"/"${GIT_REPO}".git "${APP_PATH}" && echo "    Good: Finished pulling latest codes." || exit 2
  cd "${APP_PATH}"

  echo "==> => Getting codes since COMMIT_ID=[${COMMIT_ID}] except Jenkins|Dockerfile|.md ..."
  if [ -n "${COMMIT_ID}" ]; then
    export codes=$(git log "$COMMIT_ID"^..HEAD --oneline --no-merges  --name-only |grep -v -i -E " |Dockerfile|Jenkins|\\.md|\\.txt|\\.gitignore|\\.idea.*"|sort|uniq)
    export etl_codes=$(git log "$COMMIT_ID"^..HEAD --oneline --no-merges  --name-only |grep -v -i -E " |Dockerfile|Jenkins|\\.md|\\.txt|\\.gitignore|\\.idea.*"|grep -i -E "\\.scala|\\.java|\\.sql"|sort|uniq)
    export dag_codes=$(git log "$COMMIT_ID"^..HEAD --oneline --no-merges  --name-only |grep -v -i -E " |Dockerfile|Jenkins|\\.md|\\.txt|\\.gitignore|\\.idea.*"|grep -i -E ".*/wfl/.*py"|sort|uniq)
  else
    export codes=$(git log --oneline --no-merges  --name-only |grep -v -i -E " |Dockerfile|Jenkins|\\.md|\\.txt|\\.gitignore|\\.idea.*"|sort|uniq)
    export etl_codes=$(git log --oneline --no-merges  --name-only |grep -v -i -E " |Dockerfile|Jenkins|\\.md|\\.txt|\\.gitignore|\\.idea.*"|grep -i -E "\\.scala|\\.java||\\.sql"|sort|uniq)
    export dag_codes=$(git log --oneline --no-merges  --name-only |grep -v -i -E " |Dockerfile|Jenkins|\\.md|\\.txt|\\.gitignore|\\.idea.*"|grep -i -E ".*/wfl/.*py"|sort|uniq)
  fi

  if [ -z "${codes}" ];then
    export codes_num=0
  else
    export codes_num=$(echo "$codes" | wc -l)
  fi

  echo "    etl_codes=[${etl_codes/$'\n'/,}] and dag_codes=[${dag_codes/$'\n'/,}] of $codes_num code(s)=[${codes/$'\n'/,}]."
  echo "    Finished pulling latest code."
}

build() {
  if [ -z "${codes}" ];then
    echo "NOTE: NO codes in this commit=[${COMMIT_ID} of codes=[${codes}], so skipping compiling."
    return
  fi
  echo "==> Start compiling and packaging for ${GIT_REPO} with maven profile=[${MAVEN_PROFILE}] ..."
  echo "==> => Compiling and packaging in $CDP_APP_PARENT_TAG_PATH."
  cd "$CDP_APP_PARENT_TAG_PATH"
  pwd
  mvn -q clean package -DskipTests -P "${MAVEN_PROFILE}" && echo "      Good: Finished building and packaging." || exit 2
  echo "==> Finished compiling and packaging for ${GIT_REPO} with maven profile=[${MAVEN_PROFILE}]."
}

deploy_etl_codes() {
  if [ -z "${codes}" ];then
    echo "NOTE: NO code in this commit=[${COMMIT_ID} of codes=[${codes}], so skipping deploying ETL codes in repo to the path=[${APP_PATH}] in remote server=[${REMOTE_WORKER_NODE_HOST}]."
    return
  fi

  echo "==> Start deploying ETL codes in repo to the path=[${APP_PATH}] in remote server=[${REMOTE_WORKER_NODE_HOST}] ..."
  #  echo "==> Start copying executables to the path=[${REMOTE_WORKER_REPO_PATH}] in remote server=[${REMOTE_WORKER_NODE_HOST}] ..."
  etl_home_dirs=("$CDP_APP_TAG_PATH")
  for etl_home_dir in "${etl_home_dirs[@]}"
    do
      echo "==> => Go to directory=[${etl_home_dir}]"
      cd "$etl_home_dir"
      zip_file=$(ls target/*.zip)
      zip_file_name="$(basename $zip_file)"
      target_folder_name="${zip_file_name%.*}"
      tmp_dir=/tmp
      tmp_target_folder_dir="${tmp_dir}/${target_folder_name}"
      echo "==> => Copying package zip file from $zip_file to ${tmp_dir} ... "
      scp -o StrictHostKeyChecking=no "$zip_file" "${REMOTE_WORKER_USER}@${REMOTE_WORKER_NODE_HOST}":${tmp_dir}/ && echo "==> => Good: Finished copying zip file to ${tmp_dir}." || exit 2
      echo "==> => Cleaning up ${tmp_target_folder_dir} if exists ... "
      ssh "${REMOTE_WORKER_USER}@${REMOTE_WORKER_NODE_HOST}" "if [ -d ${tmp_target_folder_dir} ]; then rm -rf ${tmp_target_folder_dir}; fi"
      echo "==> => Decompressing ${zip_file_name} under ${tmp_dir} ..."
      ssh "${REMOTE_WORKER_USER}@${REMOTE_WORKER_NODE_HOST}" "unzip ${tmp_dir}/${zip_file_name} -d ${tmp_dir}" > /dev/null || exit 2
      echo "==> => Replacing codes in $etl_home_dir with latest code ..."
      ssh "${REMOTE_WORKER_USER}@${REMOTE_WORKER_NODE_HOST}" "if ! [ -d $etl_home_dir ]; then mkdir -p $etl_home_dir; fi"
      ssh "${REMOTE_WORKER_USER}@${REMOTE_WORKER_NODE_HOST}" "cp -R ${tmp_dir}/${target_folder_name}/* $etl_home_dir" || exit 2
      echo "==> => Granting execution right to executable file ... "
      ssh "${REMOTE_WORKER_USER}@${REMOTE_WORKER_NODE_HOST}" "chmod 700 -R $etl_home_dir/bin/*" && echo "==> => Good: Finished granting execution rights to executable files"  || exit 2
    done

  echo "==> => Go to directory=[${etl_home_dir}]"
  cd $CDP_APP_ONEID_PATH
  jar_file=$(ls target/*oneid*.jar)
  jar_path=${CDP_APP_ONEID_PATH}/lib
  # in case there is any file with same name as 'bin', so remove it before attempting to create the folder with same name
  ssh -o StrictHostKeyChecking=no "${REMOTE_WORKER_USER}"@"${REMOTE_WORKER_NODE_HOST}" "if [ -f ${jar_path} ]; then rm -- ${jar_path}; fi; mkdir -p ${jar_path}"
  echo "==> => Copying package jar file from $jar_file to ${jar_path} ... "
  scp "$jar_file" "${REMOTE_WORKER_USER}"@"${REMOTE_WORKER_NODE_HOST}":"${jar_path}"/ && echo "==> => Good: Finished deploying jars." || exit 2
  echo "==> => Grant execution right to package jar file ... "
  ssh "${REMOTE_WORKER_USER}"@"${REMOTE_WORKER_NODE_HOST}" "chmod 700 -R ${jar_path}/*.jar" && echo "==> => Good: Finished granting execution rights."  || exit 2
  bin_path=${REMOTE_WORKER_REPO_PATH}/bin
  ssh -o StrictHostKeyChecking=no "${REMOTE_WORKER_USER}"@"${REMOTE_WORKER_NODE_HOST}" "if [ -f ${bin_path} ]; then rm -- ${bin_path}; fi; mkdir -p ${bin_path}"

  if [ -d bin ]; then
    echo "==> => Copying bin folder from ./bin/* to ${bin_path} ... "
    scp -o StrictHostKeyChecking=no -r bin/* "${REMOTE_WORKER_USER}"@"${REMOTE_WORKER_NODE_HOST}":"${bin_path}"/ && echo "==> => Good: Finished deploying bin folder." || exit 2
    echo "==> => Grant execution right to executables file ... "
    ssh -o StrictHostKeyChecking=no "${REMOTE_WORKER_USER}"@"${REMOTE_WORKER_NODE_HOST}" "chmod 700 -R ${bin_path}/*" && echo "==> => Good: Finished granting execution rights."  || exit 2
  fi
  echo "==> Finished deploying ALL ETL codes to the path=[${APP_PATH}] in remote server=[${REMOTE_WORKER_NODE_HOST}]."
}

deploy_dag_code_task() {
  echo "==> => Deploying Airflow DAG codes to $airflow_server ..."
  echo "==> => Copying package zip file from $zip_file to ${tmp_dir} ... "
  scp -o StrictHostKeyChecking=no "$zip_file" "${AIRFLOW_SERVER_USER}@${airflow_server}":${tmp_dir}/ && echo "==> => Good: Finished copying zip file to ${tmp_dir}."
  echo "==> => Cleaning up ${tmp_target_folder_dir} if exists ... "
  ssh "${AIRFLOW_SERVER_USER}@${airflow_server}" "if [ -d ${tmp_target_folder_dir} ]; then rm -rf ${tmp_target_folder_dir}; fi"
  echo "==> => Decompressing ${zip_file_name} under ${tmp_dir} ..."
  ssh "${AIRFLOW_SERVER_USER}@${airflow_server}" "unzip ${tmp_dir}/${zip_file_name} -d ${tmp_dir}" > /dev/null
  echo "==> => Replacing codes in $CDP_APP_TAG_PATH with latest code ..."
  ssh "${AIRFLOW_SERVER_USER}@${airflow_server}" "cp -R ${tmp_dir}/${target_folder_name}/${CDP_DAG_RELATIVE_PATH}/*.py ${AIRFLOW_DAG_PATH}"
  echo "==> => Finished deploying DAG codes to the path=[${APP_PATH}] in Airflow server=[${airflow_server}]."
}

deploy_dag_codes() {
  if [ -z "${AIRFLOW_SERVER_LIST}" ]; then
    echo "ERROR: environment variable 'AIRFLOW_SERVER_LIST' is NOT set. Please set and pass it to docker run --env AIRFLOW_SERVER_LIST=xx. !!!"
    exit 2
  fi

  if [ -z "${dag_codes}" ];then
    echo "NOTE: NO dag codes in this commit=[${COMMIT_ID}, so skipping deploying Airflow DAG codes in repo to the path=[${APP_PATH}] in Airflow server=[${AIRFLOW_SERVER_LIST}]."
    return
  fi

  export dag_codes_num=$(echo "${dag_codes}" | wc -l)
  echo "==> Start deploying Airflow DAG codes in repo to the path=[${APP_PATH}] in Airflow server=[${AIRFLOW_SERVER_LIST}] ..."
  cd "$CDP_APP_TAG_PATH"
  zip_file=$(ls target/*.zip)
  zip_file_name="$(basename $zip_file)"
  target_folder_name="${zip_file_name%.*}"
  tmp_dir=/tmp
  tmp_target_folder_dir="${tmp_dir}/${target_folder_name}"
  IFS=',' read -ra airflow_server_array <<< "${AIRFLOW_SERVER_LIST}"
  for airflow_server in "${airflow_server_array[@]}"
  do
    attempt_count=0
    while [ 0 -eq 0 ]
    do
        deploy_dag_code_task
        if [ "$?" -eq 0 ]; then
          break;
        else
          echo "==> => Failed to deploy DAG codes to the path=[${APP_PATH}] in Airflow server=[${airflow_server}]."
          attempt_count=$[${attempt_count}+1]
          if [ "${attempt_count}" -eq "${CDP_MAX_DAG_DEPLOYMENT_ATTEMPT_COUNT}" ]; then
              echo "ERROR: Reach max attempt count=[${CDP_MAX_DAG_DEPLOYMENT_ATTEMPT_COUNT}]"
              exit 2
          fi
          echo "==> => Retry in ${CDP_MAX_DAG_DEPLOYMENT_ATTEMPT_SLEEP_IN_SECS} second(s) ..."
          sleep "${CDP_MAX_DAG_DEPLOYMENT_ATTEMPT_SLEEP_IN_SECS}"
        fi
    done
  done
  echo "==> Finished deploying DAG codes to the path=[${APP_PATH}] in ALL Airflow server list=[${AIRFLOW_SERVER_LIST}]."
}


cmd=$1
echo "$cmd"

pull
build
deploy_etl_codes
deploy_dag_codes
echo "Good: ALL CI/CD tasks are finished."
exec "$@"